package com.android.volley.images;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;

import java.security.InvalidParameterException;

/**
 * @author ChameleonChen
 */
public class ImageDataLoader {

    private final RequestQueue mRequestQueue;

    private final ImageCache mCache;

    public ImageDataLoader(RequestQueue requestQueue, ImageCache cache) {
        if (requestQueue == null || cache == null)
            throw new InvalidParameterException();

        this.mRequestQueue = requestQueue;
        this.mCache = cache;
    }

    public ImageDataListener getListener(final ImageDataOperator imageView, final int defDrawableId, final int errDrawableId) {
        return new ImageDataListener() {
            @Override
            public void onResponse(byte[] response, boolean isImmediate) {
                if (response != null && response.length > 0) {
                    imageView.setImageData(response);
                } else if (defDrawableId != 0) {
                    imageView.setImageResource(defDrawableId);
                }
            }

            @Override
            public void onErrorResponse(VolleyError error) {
                if (errDrawableId != 0) {
                    imageView.setImageResource(errDrawableId);
                }
            }
        };
    }

    public interface ImageDataListener extends Response.ErrorListener{

        /**
         * Listens for non-error changes to the loading of the image request.
         *
         * @param response Holds all information pertaining to the request, as well
         * as the bitmap (if it is loaded).
         * @param isImmediate True if this was called during ImageLoader.get() variants.
         * This can be used to differentiate between a cached image loading and a network
         * image loading in order to, for example, run an animation to fade in network loaded
         * images.
         */
        public void onResponse(byte[] response, boolean isImmediate);
    }

    /**
     * This is image data cache with byte[] format.
     */
    public interface ImageCache {
        public void setData(String url, byte[] data);
        public byte[] getData(String url);
    }

    public static String getCacheKey(String url) {
        return url;
    }

    /**
     * To get the image data associate with the image url,
     * if cache did not contains the data, the request form network.
     * @param url
     * @param listener
     */
    public void get(String url, final ImageDataListener listener) {
        final String cacheKey = getCacheKey(url);

        // check cache
        byte[] data = mCache.getData(url);
        if (data != null) {     // data has already stored in cache
            listener.onResponse(data, true);
        }

        // if cache has not stored data, request data from network.
        Request<byte[]> request = new ImageDataRequest(url,
                new Response.Listener<byte[]>(){
                    @Override
                    public void onResponse(byte[] response) {
                        saveToCache(cacheKey, response);
                        listener.onResponse(response, true);
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        listener.onErrorResponse(error);
                    }
                });
        mRequestQueue.add(request);
    }

    public void saveToCache(String key, byte[] data) {
        mCache.setData(key, data);
    }
}
